package com.xyhuo.leetcode;

import org.apache.commons.collections4.sequence.EditScript;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionObject {

    private String name;

    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

class ReflectTest {
    private static void jdkReflection() {
        Class<ReflectionObject> clazz = ReflectionObject.class;
        try {
            Constructor<ReflectionObject> constructor = clazz.getConstructor();
            ReflectionObject instance = constructor.newInstance();

            Method setNameMethod = clazz.getDeclaredMethod("setName", String.class);
            setNameMethod.invoke(instance, "菜鸡");


            Field ageField = clazz.getDeclaredField("age");
            ageField.setAccessible(true);
            ageField.set(instance, 18);
        } catch (Exception ex) {

        }
    }


    private static void springReflection() {
        Constructor<ReflectionObject> constructor = null;
        ReflectionObject instance = null;

        try {
            constructor = ReflectionUtils.accessibleConstructor(ReflectionObject.class);
            instance = constructor.newInstance();
        } catch (Exception ex) {

        }

        Method setNameMethod = ReflectionUtils.findMethod(ReflectionObject.class, "setName");
        if (null != setNameMethod) {
            ReflectionUtils.invokeMethod(setNameMethod, instance, "菜鸡");
        }

        Field ageField = ReflectionUtils.findField(ReflectionObject.class, "age");
        if (null != ageField) {
            ReflectionUtils.makeAccessible(ageField);
            ReflectionUtils.setField(ageField, instance, 18);
        }
    }

    public static void main(String[] args) {
//        differentTimeCosts(1);
//        differentTimeCosts(1000);
//        differentTimeCosts(10000);
//        differentTimeCosts(100000);
//        differentTimeCosts(1000000);
//        differentTimeCosts(10000000);


        differentTimeCostsSpring(1);
        differentTimeCostsSpring(1000);
        differentTimeCostsSpring(10000);
        differentTimeCostsSpring(100000);
        differentTimeCostsSpring(1000000);
        differentTimeCostsSpring(10000000);
    }

    private static void differentTimeCosts(int count) {
        long before = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            jdkReflection();
        }
        long after = System.currentTimeMillis();
        long costTime = after - before;
        System.out.println(String.format("调用%s次，耗时：%s ms", count, costTime));
    }

    private static void differentTimeCostsSpring(int count) {
        long before = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            springReflection();
        }
        long after = System.currentTimeMillis();
        long costTime = after - before;
        System.out.println(String.format("调用%s次，耗时：%s ms", count, costTime));
    }
}
